;(function (factory) {
    if (typeof define === 'function' && define.amd) {
        define(['jquery'], factory);
    } else if (typeof exports === 'object') {
        factory(require('jquery'));
    } else {
        factory(jQuery);
    }
}(function ($) {
    $.fn.pagination = function (options) {
        var defaults = {
            'total': 5,
            'maxPage': 5,
            'currentPage': 1,
            'prev': '&lt;',
            'next': '&gt;',
            'url': '',
            'ajax': 'get',
            'data': {},
            'target': ''
        };
        var self = this;
        var $this = $(this);

        this.settings = $.extend(defaults, options);

        var _init = function () {
            var $page = _buildList(self.settings.currentPage);
            $this.append($page);
            $("[data-page=" + self.settings.currentPage + "]").removeClass("btn-default").addClass('btn-primary');
            bind();
        };

        var _buildBtn = function (id, html) {
            return id != null ? $("<button>", {"type": "button", "class": "btn btn-default", "data-page": id}).html(html)
                : $("<button>", {"type": "button", "class": "btn btn-default"}).html(html);
        };

        var _buildId = function (id) {
            return id;
        };

        var _buildList = function (page) {
            var $page = $("<div>", {'class': "btn-group pull-right"})
                .append($("<button>", {"type": "button", "class": "btn btn-default", "data-page": "prev"}).html(self.settings.prev));
            var j = parseInt(self.settings.maxPage / 2);
            var first = (page - j) < 1 ? 1 : (page - j);
            var total = (page + j) > self.settings.total ? self.settings.total : (page + j);
            if (page > 1 + j) {
                $page.append(_buildBtn(_buildId(1), 1))
                    .append(_buildBtn("omit", '...'));
            }
            for (var i = first; i <= total; i++) {
                $page.append(_buildBtn(_buildId(i), i));
            }
            if ((page + j) < self.settings.total) {
                $page.append(_buildBtn("omit", '...'))
                    .append(_buildBtn(_buildId(self.settings.total), self.settings.total));
            }
            $page.append($("<button>", {"type": "button", "class": "btn btn-default", "data-page": "next"}).html(self.settings.next));
            return $page;
        };

        var bind = function () {
            $this.on("click", "button", function () {
                var page = $(this).data('page');
                var cPage = $this.find(".btn-primary");
                if (page == 'prev') {
                    if (cPage.data("page") == 1) {
                        return false;
                    }
                    page = cPage.data("page") - 1;
                } else if (page == 'next') {
                    if (cPage.data("page") == self.settings.total) {
                        return false;
                    }
                    page = cPage.data("page") + 1;
                } else if (page == 'omit') {
                    return false;
                }
                $this.html(_buildList(page));
                cPage.removeClass("btn-primary").addClass("btn-default");
                $this.find("[data-page=" + page + "]:first").removeClass("btn-default").addClass('btn-primary');
                if (self.settings.ajax) {
                    self.settings.data['page'] = page;
                    $.ajax({
                        'url': self.settings.url,
                        'type': self.settings.ajax.toLowerCase() === "post" ? "post" : "get",
                        'data': self.settings.data,
                        success: function (data) {
                            $(self.settings.target).html(data)
                        }
                    })
                } else {
                    windows.locale.href = self.settings.url;
                }
            });
        };

        _init();
        return this;
    }
}));